package com.example.guli.service.ucenter.controller.api;

import com.alibaba.nacos.client.utils.StringUtils;
import com.example.guli.common.base.result.ResultCodeEnum;
import com.example.guli.service.base.exception.ExceptionUtils;
import com.example.guli.common.base.util.HttpClientUtils;
import com.example.guli.common.base.util.jwt.JwtInfo;
import com.example.guli.common.base.util.jwt.JwtUtils;
import com.example.guli.service.base.exception.GuliException;
import com.example.guli.service.ucenter.entity.Member;
import com.example.guli.service.ucenter.service.MemberService;
import com.example.guli.service.ucenter.util.UcenterProperties;
import com.google.gson.Gson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@CrossOrigin
@Controller//注意这里没有配置 @RestController
@Api(description = "微信登录")
@RequestMapping("/api/ucenter/wx")
@Slf4j
public class ApiWxController {
    @Autowired
    private UcenterProperties ucenterProperties;//读取微信登录的配置
    @Autowired
    private MemberService memberService;

    @ApiOperation(value = "获取code，生成二维码，以供用户扫码登录")
    @GetMapping("login")
    public String genQrConnect(HttpSession session){
        // 组装URL：https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        //处理回调url，转码
        String redirecturi = "";
        try {
            redirecturi = URLEncoder.encode(ucenterProperties.getRedirectUri(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(ExceptionUtils.getMessage(e));
            throw new GuliException(ResultCodeEnum.URL_ENCODE_ERROR);
        }

        //处理state：生成随机数，存入session，防止csr攻击
        String state = UUID.randomUUID().toString();
        log.info("生成 state = " + state);
        //将state存入session
        session.setAttribute("wx_open_state", state);

        //创建格式化的字符串以及连接多个字符串对象
        String qrcodeUrl = String.format(
                baseUrl,
                ucenterProperties.getAppId(),
                redirecturi,
                state
        );

        return "redirect:" + qrcodeUrl;
        //https://open.weixin.qq.com/connect/qrconnect?appid=wxed9954c01bb89b47&redirect_uri=http%3A%2F%2Fguli.shop%2Fapi%2Fucenter%2Fwx%2Fcallback8160&response_type=code&scope=snsapi_login&state=d5d4930f-8724-4153-bc80-6fb33d7057ca#wechat_redirect
    }

    //扫码登录，用户点击同意，即可获取code：http://guli.shop/api/ucenter/wx/callback8160?code=031HTXZv3lnt6V27Lh2w3jK0W02HTXZi&state=d9d05adf-43e0-4f10-8a82-dc37efd15850
    @ApiOperation(value = "微信扫码登录回调api")
    @GetMapping("callback")
    public String callback(String code, String state, HttpSession session){
        //回调被拉起，并获得code和state参数
        System.out.println("callback被调用");
        System.out.println("code = " + code);
        System.out.println("state = " + state);
        System.out.println("session = " + session);
        System.out.println("session = " + session.getSessionContext());


        if(StringUtils.isEmpty(code) || StringUtils.isEmpty(state) ){
            log.error("非法回调请求");
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }

        String sessionState = (String)session.getAttribute("wx_open_state");
        if(!state.equals(sessionState)){
            log.error("非法回调请求");
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }

        //携带授权临时票据code，和appid以及appsecret请求access_token
        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
        //组装参数?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        Map<String, String> accessTokenParam = new HashMap<>();
        accessTokenParam.put("appid", ucenterProperties.getAppId());
        accessTokenParam.put("secret", ucenterProperties.getAppSecret());
        accessTokenParam.put("code", code);
        accessTokenParam.put("grant_type", "authorization_code");
        HttpClientUtils client = new HttpClientUtils(accessTokenUrl, accessTokenParam);

        String result = "";
        try {
            //发送http请求：组装完整的URL参数，发送请求
            client.get();
            //得到响应
            result = client.getContent();
            System.out.println("result = " + result);
        } catch (Exception e) {
            log.error("获取access_token失败");
            throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
//      {
//                "access_token": "37_GnEO3gD9kTiBmQ312bKR0pHMmqLYab1SkQs84i6B5Xo8OJe46K9hlFr_lq-6K3LRyYkX3i-cz-kDxyOBM0hNwMuFyQJomE8-iCa0jrFYL50",
//                "expires_in": 7200,//超时时间
//                "refresh_token": "37_Ve7ZLa1rD3xU6HZzvuHVrYLDuX1ZO7k3nE5b_fmad2zdLjZzSsGUbeTNuQko1QwINLo9DHmR06MRPXTdjdN1AI3mONvXbvhgcHu9xiYGF2I",
//                "openid": "o3_SC59hTghskhdvQKGT10q0W8Oc",//微信唯一标识
//                "scope": "snsapi_login",
//                "unionid": "oWgGz1DXapNdmwlAAPWvtD_oXjos"
//        }

        //解析json
        Gson gson = new Gson();
        HashMap<String, Object> resultMap = gson.fromJson(result, HashMap.class);

        //判断微信获取access_token失败的响应
        Object errcodeObj = resultMap.get("errcode");
        if(errcodeObj != null){
            String errmsg = (String)resultMap.get("errmsg");
            Double errcode = (Double)errcodeObj;
            log.error("获取access_token失败 - " + "message: " + errmsg + ", errcode: " + errcode);
            throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }

        //微信获取access_token响应成功
        String accessToken = (String)resultMap.get("access_token");
        String openid = (String)resultMap.get("openid");
        log.info("accessToken = " + accessToken);
        log.info("openid = " + openid);

        //根据access_token获取微信用户的基本信息
        // TODO


        //在本地数据库中查询当前微信用户信息
        Member member = memberService.getByOpenid(openid);
        if(member == null){
            //if如果当前用户不存在，则去微信的资源服务器获取个人信息（携带access_token）
            //在本地数据库插入当前微信用户的信息（使用微信账号在本地服务器注册新用户）
            //使用当前用户的信息登录（生成jwt）

            //向微信的资源服务器发起请求，获取当前用户的用户信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo";
            Map<String, String> baseUserInfoParam = new HashMap<>();
            baseUserInfoParam.put("access_token", accessToken);
            baseUserInfoParam.put("openid", openid);
            client = new HttpClientUtils(baseUserInfoUrl, baseUserInfoParam);

            String resultUserInfo = null;
            try {
                //发送http请求：组装完整的URL参数，发送请求
                client.get();
                resultUserInfo = client.getContent();
            } catch (Exception e) {
                log.error(ExceptionUtils.getMessage(e));
                throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }
            //解析结果
            HashMap<String, Object> resultUserInfoMap = gson.fromJson(resultUserInfo, HashMap.class);
            if(resultUserInfoMap.get("errcode") != null){
                log.error("获取用户信息失败" + "，message：" + resultMap.get("errmsg"));
                throw new GuliException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }
            //解析结果中的用户个人信息
            String nickname = (String)resultUserInfoMap.get("nickname");
            String headimgurl = (String)resultUserInfoMap.get("headimgurl");
            Double sex = (Double)resultUserInfoMap.get("sex");

            //用户注册(使用微信账号在本地服务器注册新用户）
            member = new Member();
            member.setOpenid(openid);
            member.setNickname(nickname);
            member.setAvatar(headimgurl);
            member.setSex(sex.intValue());
            memberService.save(member);
        }

        //else如果当前用户已存在，则直接使用用户信息登录（生成jwt）
        //如果当前用户不存在，注册之后就要登录了，这样可以避免重复书写登录的代码了
        JwtInfo jwtInfo = new JwtInfo();
        jwtInfo.setId(member.getId());
        jwtInfo.setNickname(member.getNickname());
        jwtInfo.setAvatar(member.getAvatar());
        String jwtToken = JwtUtils.getJwtToken(jwtInfo, 86400);

        //携带token跳转
        return "redirect:http://localhost:3000?token=" + jwtToken;
    }
}
